﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Assistant.WebHelper;

/**
 * 创建时间：2014/10/29 14:42:58
 * 作者：yong.blackcore
 * Email：itblackhole@outlook.com
 * QQ：50404503
 * Descrition:http://www.kuaipan.cn/developers/document_oauth.htm#item1
 */
namespace Assistant.KuaiPan
{
    public class KuaiPanHelper
    {
        private const string CONSUMER_KEY = "xcO1aUZHjMveS8W0";
        private const string CONSUMER_SECRET = "2L3t5rQcaOk1YybN";
        private const string OAuth_Version = "1.0";
        private const string URL_RequestToken = "https://openapi.kuaipan.cn/open/requestToken";

        #region 授权认证
        /// <summary>
        /// 获取未授权的临时 token
        /// <para>https://openapi.kuaipan.cn/open/requestToken</para>
        /// </summary>
        public string GetRequestToken()
        {
            string result = string.Empty;
            StringBuilder requestUrl = new StringBuilder();
            requestUrl.Append(URL_RequestToken).Append("?");
            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("oauth_consumer_key", CONSUMER_KEY);
            parameters.Add("oauth_nonce", new Random().Next(100000, 99999999).ToString());
            parameters.Add("oauth_signature_method", "HMAC-SHA1");
            parameters.Add("oauth_timestamp", TimeStampHelper.ConvertLocalToTimestamp(DateTime.Now).ToString());
            parameters.Add("oauth_version", OAuth_Version);
            string signature = GetOAuthSignature("GET", URL_RequestToken, parameters);
            //
            requestUrl.Append("oauth_signature=").Append(signature);
            foreach (var item in parameters)
            {
                requestUrl.Append("&");
                requestUrl.Append(item.Key).Append("=").Append(item.Value);
            }

            LogHelper.LogInfo(requestUrl.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            //Request(requestUrl.ToString());
            //WebTaskHelper webTask = new WebTaskHelper(new Uri(requestUrl.ToString()));
            //IAsyncResult ia = webTask.BeginWebTask(delegate(IAsyncResult callBackResult)
            //{
            //    result = webTask.EndWebTask(callBackResult);
            //}, webTask);
            //return result;
            return requestUrl.ToString();
        }


        public string GetAuthorize(string requestToken)
        {
            return "https://www.kuaipan.cn/api.php?ac=open&op=authorise&oauth_token=" + requestToken;
        }

        public string GetAccountInfo(string oauthToken)
        {
            string url = "http://openapi.kuaipan.cn/1/account_info";
            string result = string.Empty;
            StringBuilder requestUrl = new StringBuilder();
            requestUrl.Append(url).Append("?");
            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("oauth_consumer_key", CONSUMER_KEY);
            parameters.Add("oauth_nonce", new Random().Next(100000, 99999999).ToString());
            parameters.Add("oauth_signature_method", "HMAC-SHA1");
            parameters.Add("oauth_timestamp", TimeStampHelper.ConvertLocalToTimestamp(DateTime.Now).ToString());
            parameters.Add("oauth_version", OAuth_Version);
            parameters.Add("oauth_token", oauthToken);
            string signature = GetOAuthSignature("GET", url, parameters,oauthToken);
            //
            requestUrl.Append("oauth_signature=").Append(signature);
            foreach (var item in parameters)
            {
                requestUrl.Append("&");
                requestUrl.Append(item.Key).Append("=").Append(item.Value);
            }

            LogHelper.LogInfo(requestUrl.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            //
            return requestUrl.ToString();
        }

        public string GetAccessToken(string oauthToken)
        {
            string url = "https://openapi.kuaipan.cn/open/accessToken";
            string result = string.Empty;
            StringBuilder requestUrl = new StringBuilder();
            requestUrl.Append(url).Append("?");
            Dictionary<string, string> parameters = new Dictionary<string, string>();
            
            parameters.Add("oauth_nonce", new Random().Next(100000, 99999999).ToString());
            
            parameters.Add("oauth_timestamp", TimeStampHelper.ConvertLocalToTimestamp(DateTime.Now).ToString());
            parameters.Add("oauth_consumer_key", CONSUMER_KEY);
            parameters.Add("oauth_signature_method", "HMAC-SHA1");
            
            string signature = GetOAuthSignature("GET", url, parameters, oauthToken);
            //
            requestUrl.Append("oauth_signature=").Append(signature);
            parameters.Add("oauth_vrsion", OAuth_Version);
            parameters.Add("oauth_token", oauthToken);
            foreach (var item in parameters)
            {
                requestUrl.Append("&");
                requestUrl.Append(item.Key).Append("=").Append(item.Value);
            }

            LogHelper.LogInfo(requestUrl.ToString(), this.GetType(), MethodBase.GetCurrentMethod());
            //
            return requestUrl.ToString();
        }
        #endregion 授权认证

        #region 签名算法
        private string GetOAuthSignature(string httpMethod, string requestUrl, Dictionary<string, string> parameters, string oauth_token = "")
        {
            StringBuilder encryptContent = new StringBuilder();
            encryptContent.Append(httpMethod).Append("&").Append(Uri.EscapeDataString(requestUrl)).Append("&");

            StringBuilder baseStringParams = new StringBuilder();
            foreach (var item in parameters)
            {
                baseStringParams.Append(string.Join("=", new string[] { Uri.EscapeDataString(item.Key), Uri.EscapeDataString(item.Value) }));
                baseStringParams.Append("&");
            }
            string baseString = baseStringParams.ToString().Substring(0, baseStringParams.ToString().Length - 1);
            encryptContent.Append(Uri.EscapeDataString(baseString));
            LogHelper.LogInfo(baseString.ToString());
            //

            string result = GetHMACSHA1(encryptContent.ToString(), GetEncryptKey(CONSUMER_SECRET, oauth_token));
            //GetHMACSHA1已经有了Base64
            result = Uri.EscapeDataString(result);
            LogHelper.LogInfo(result);

            return result;
        }

        private string GetEncryptKey(string consumer_secret, string oauth_token)
        {
            return string.Concat(consumer_secret, "&", oauth_token);
        }

        private string GetHMACSHA1(string encryptText, string encryptKey)
        {
            HMACSHA1 hmacsha1 = new HMACSHA1();
            hmacsha1.Key = System.Text.Encoding.UTF8.GetBytes(encryptKey);
            byte[] dataBuffer = System.Text.Encoding.UTF8.GetBytes(encryptText);
            byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer);
            return Convert.ToBase64String(hashBytes);
        }
        #endregion 签名算法

        private void Request(string requestUrl)
        {
            HttpWebRequest request = null;
            try
            {
                request = HttpWebRequest.CreateHttp(new Uri(requestUrl));

                request.Method = "GET";
                request.BeginGetResponse(ResponseCallback, request);
            }
            catch (Exception err)
            {
                if (request != null)
                {
                    request.Abort();
                }
                LogHelper.LogInfo(err.Message, this.GetType());
            }
            finally
            {
                //异步的，不能终止
            }
        }

        private void ResponseCallback(IAsyncResult asynchronousResult)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            StreamReader streamRead = null;
            string content = string.Empty;
            try
            {
                request = (HttpWebRequest)asynchronousResult.AsyncState;
                response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
                //获取应答码
                int statusCode = Convert.ToInt32(response.StatusCode);
                string statusText = response.StatusDescription;

                //应答头信息验证
                using (Stream streamResponse = response.GetResponseStream())
                {
                    //获取请求信息
                    streamRead = new StreamReader(streamResponse, Encoding.UTF8);
                    if (streamRead != null)
                    {
                        content = streamRead.ReadToEnd();
                        if (!string.IsNullOrWhiteSpace(content))
                        {
                            //{"oauth_token_secret":"9847a2d988c4402c960ba73872e8d0a3","oauth_token":"05f34edbd5b542d8b0a93470b7ec0138","expires_in":1800,"oauth_callback_confirmed":false}
                            LogHelper.LogInfo("ResponseCallback is result:\r\n" + content, this.GetType());
                        }
                        else
                        {
                            LogHelper.LogInfo("ResponseCallback result has empty", this.GetType());
                        }
                    }
                }
            }
            catch (Exception err)
            {
                LogHelper.LogError("ResponseCallback has error:\r\n" + err.Message, this.GetType());

            }
            finally
            {
                //
                if (streamRead != null)
                {
                    streamRead.Close();
                    streamRead.Dispose();
                }
                if (response != null)
                {
                    response.Close();
                    response.Dispose();
                }
                if (streamRead != null)
                    streamRead.Dispose();
                if (request != null)
                    request.Abort();
            }
        }
    }
}
